﻿using AttributeRouting.Web.Http;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Helpers;
using System.Web.Mvc;
using _2009035.Models;
using _2009035.Utilities;
using Kendo.Mvc.Extensions;
using System.Web.Security;

namespace _2009035.Controllers
{
    //[RequireHttps]
    public class EmployeeController : Controller
    {
        private DbEntities db = new DbEntities();

  
       
        //
        // GET: /Employee/
        [Authorize]
        public ActionResult Personal()
        {
            int id;
            int.TryParse(User.Identity.Name, out id);
            var currentEmployee = db.Employees.FirstOrDefault(x => x.employeeNumber == id);
            return View(currentEmployee);
        }


        public ActionResult Search()
        {
            return View();
        }

        [Authorize(Roles = "HRManager,HRExecutive")]
       
        public ActionResult Manage()
        {
            return View();
        }

        /// <summary>
        /// Method that checks if the user is in the administrator
        /// role or if he has sufficient permissions to view 
        /// aspects of details returned by the system
        /// </summary>
        /// <returns>
        /// Two variables in a JSON object
        /// </returns>
        public JsonResult GetAuthentication()
        {
            bool isAdmin = false;
            bool isConfidential = false;

            // check if the user is the administrator of the system
            if (User.IsInRole(Utility.GetEnumDescription(UserRoles.HRManager)))
            {
                isAdmin = true;
                isConfidential = true;
            }

            else if ((User.IsInRole(Utility.GetEnumDescription(UserRoles.Manager))) || User.IsInRole(Utility.GetEnumDescription(UserRoles.Employee)))
            {
                isConfidential = false;
            }

            // TODO Remove
            isAdmin = isConfidential = true;
            return Json(new { isAdmin = isAdmin, isConfidential = isConfidential}, JsonRequestBehavior.AllowGet);
        }

        //
        // GET: /Employee/Details/5
        [AllowAnonymous]
        public ActionResult Details(int id)
        {
            Employee employee = db.Employees.Find(id);
            if (employee == null)
            {
                return HttpNotFound();
            }
            return View(employee);
        }

        [Authorize (Roles= "HRManager")]
        public ActionResult SalaryHistory()
        {
            int empNo;
            int.TryParse(User.Identity.Name, out empNo);
            Employee employee = db.Employees.FirstOrDefault(x => x.employeeNumber == empNo);
            return View(employee.Salaries);
        }

        [AllowAnonymous]  
        public IQueryable<Employee> PopulateEmployees()
        {
            IEnumerable<Employee> employees = db.Employees.ToList().Select(x => new Employee() { employeeNumber = x.employeeNumber, firstName = x.firstName, lastName = x.lastName, birthDate = x.birthDate });
            var employeeQueryable = employees.AsQueryable();
            return employeeQueryable;
        }
       
        //
        // POST: /Employee/Create

        [HttpPost]
        public ActionResult Create(GridEmployee grid)
        {
            try
            {
                if (grid != null)
                {
                    string department = Utility.GetEnumDescription((Departments)Enum.Parse(typeof(Departments), grid.department));
                    string title = Utility.GetEnumDescription((Titles)Enum.Parse(typeof(Titles), grid.title));


                    // add the employee to the database
                    Employee employee = new Employee()
                    {
                        employeeNumber = grid.employeeNumber,
                        firstName = grid.firstName,
                        lastName = grid.lastName,
                        gender = grid.gender,
                        hireDate = grid.hireDate,
                        birthDate = grid.birthDate

                    };

                    Title employeeTitle = new Title()
                    {
                        employeeNumber = employee.employeeNumber,
                        fromDate = grid.hireDate,
                        title1 = title,
                        toDate = Constants.EndDateAsCurrent

                    };



                    DepartmentEmployee employeeDepartment = new DepartmentEmployee()
                    {
                        employeeNumber = grid.employeeNumber,
                        fromeDate = grid.hireDate,
                        toDate = Constants.EndDateAsCurrent,
                        departmentNumber = db.Departments.First(x => x.departmentName == department).departmentNumber,
                    };

                    db.Employees.Add(employee);
                    db.Titles.Add(employeeTitle);
                    db.DepartmentEmployees.Add(employeeDepartment);
                    db.SaveChanges();

                    Salary employeeSalary = new Salary()
                    {
                        employeeNumber = employee.employeeNumber,
                        salary1 = grid.salary,
                        fromDate = grid.hireDate,
                        toDate = Constants.EndDateAsCurrent
                    };

                    db.Salaries.Add(employeeSalary);
                    db.SaveChanges();

                    return Json(new { Success = true });
                }
                else
                {
                    return Json(new { Success = false, Message = "Empty" });
                }
               
            }
            catch (Exception ex)
            {
                return Json(new { Success = false, Message = ex.Message });
            }            
        }

        //
        // GET: /Employee/Edit/5

        [POST("employee/Edit")]
        public ActionResult Edit(int employeeNumber)
        {
            Employee employee = db.Employees.Find(employeeNumber);

            // if something goes wrong and the employee cannot be found
            if (employee == null)
            {
                return HttpNotFound();
            }
            else
            {
                return null;
            }           
        }

      
        // GET: /Employee/Delete/5
       
        public ActionResult Delete(int id = 0)
        {
            Employee employee = db.Employees.Find(id);
            if (employee != null)
            {
                //db.Employees.Remove(employee);
                //db.SaveChanges();
                Membership.DeleteUser(User.Identity.Name, true);
                return Json(new { Success = true});
            }

            return Json(new { Success = false });
        }

        //
        // POST: /Employee/Delete/5

        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(int id)
        {
            Employee employee = db.Employees.Find(id);
            db.Employees.Remove(employee);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        //[Authorize(Roles = "HRManager")]
        [POST("employee/GetSalaryLog")]
        public JsonResult GetSalaryLog(Request request)
        {
            System.Func<Salary, GridSalary> secondarySelector = x => new GridSalary() { employeeNumber = x.employeeNumber, salary = x.salary1, fromDate = x.fromDate, toDate = x.toDate};            
            int empNo;

            // TODO Remove the user of USER.IDENTITY
            int.TryParse(request.employeeNumber, out empNo);
            Employee employee = db.Employees.FirstOrDefault(x => x.employeeNumber == empNo);
            IEnumerable<GridSalary> salaries = employee.Salaries.Select(secondarySelector);
            IQueryable<GridSalary> salaryQuery = salaries.OrderByDescending(x => x.fromDate).Skip(request.skip).Take(request.take).AsQueryable();

            return this.Json(new Response(salaryQuery.ToArray(), salaries.Count()), JsonRequestBehavior.AllowGet);
        }

        [POST("employee/GetTitleLog")]
        public JsonResult GetTitleLog(Request request)
        {
            System.Func<Title, GridTitle> secondarySelector = x => new GridTitle() { employeeNumber = x.employeeNumber, title = x.title1, fromDate = x.fromDate, toDate = x.toDate };
            int empNo;
            int.TryParse(request.employeeNumber, out empNo);
            Employee employee = db.Employees.FirstOrDefault(x => x.employeeNumber == empNo);            
            IEnumerable<GridTitle> titles = employee.Titles.Select(secondarySelector);
            IQueryable<GridTitle> titleQuery = titles.OrderByDescending(x => x.fromDate).Skip(request.skip).Take(request.take).AsQueryable();

            return this.Json(new Response(titleQuery.ToArray(), titles.Count()), JsonRequestBehavior.AllowGet);
        }

        [POST("employee/AddSalary")]
        public JsonResult AddSalary(GridSalary request)
        {
            if (request != null)
            {
                // check if the user has an employee number
                if (request.employeeNumber > 0)
                {
                    // get a list of salaries and order based on from date                    
                    var lastSalary = GetLastSalary(request.employeeNumber);

                    if (lastSalary != null)
                    {
                        // if the salary is in the same date
                        if (lastSalary.toDate == request.fromDate)
                        {
                            // lastSalary.
                            lastSalary.salary1 = request.salary;
                        }
                        else
                        {
                            lastSalary.toDate = request.fromDate;
                            // db.SaveChanges();
                        }
                    }                  

                    var newSalary = new Salary()
                    {
                        employeeNumber = request.employeeNumber,
                        fromDate = request.fromDate,
                        toDate = Constants.EndDateAsCurrent,
                        salary1 = request.salary
                    };

                    db.Salaries.Add(newSalary);
                    db.SaveChanges();
                }
            }

            return null;
        }


        public JsonResult AddTitle(GridTitle request)
        {
            if (request != null)
            {
                try
                {
                    // check if the user has an employee number
                    if (request.employeeNumber > 0)
                    {
                        // get a list of salaries and order based on from date                       
                        var lastTitle = GetLastTitle(request.employeeNumber);

                        if (lastTitle != null)
                        {
                            // if the salary is in the same date
                            if (lastTitle.toDate == request.fromDate)
                            {
                                // lastSalary.
                                lastTitle.title1 = request.title;
                            }
                            else
                            {
                                lastTitle.toDate = request.fromDate;
                            }
                        }

                        var newTitle = new Title()
                        {
                            employeeNumber = request.employeeNumber,
                            fromDate = request.fromDate,
                            toDate = Constants.EndDateAsCurrent,
                            title1 = request.title
                        };

                        // if the new title is a manager. Check if the current department of 
                        // the employee has a manager. if he has then error. else add to db

                        db.Titles.Add(newTitle);
                        db.SaveChanges();
                        return Json("Success");
                    }
                }
                catch (Exception)
                {
                    
                    throw;
                }
                
            }

            return Json("Failed");
        }



        /// <summary>
        /// Removes the salary.
        /// </summary>
        /// <param name="employeeNumber">The employee number.</param>
        /// <returns>
        /// Removes the last salary entered and  makes n-1th 
        /// to date to 9999-01-01
        /// </returns>
        public JsonResult RemoveSalary(int employeeNumber)
        {
            if (employeeNumber > 0)
            {
                // get a list of salaries and order based on from date
                var lastSalary = GetLastSalary(employeeNumber);
                db.Salaries.Remove(lastSalary);
                db.SaveChanges();
                lastSalary = GetLastSalary(employeeNumber);
                lastSalary.toDate = Constants.EndDateAsCurrent;
                db.SaveChanges();
            }

            return null;
        }


        public JsonResult RemoveTitle(int employeeNumber)
        {
            if (employeeNumber > 0)
            {
                // get a list of salaries and order based on from date
                var lastTitle = GetLastTitle(employeeNumber);
                db.Titles.Remove(lastTitle);
                db.SaveChanges();
                lastTitle = GetLastTitle(employeeNumber);
                lastTitle.toDate = Constants.EndDateAsCurrent;
                db.SaveChanges();
            }

            return null;
        }

        /// <summary>
        /// Gets the last salary.
        /// </summary>
        /// <param name="employeeNumber">The employee number.</param>
        /// <returns>
        /// Returns the latest salary, if there is
        /// no salary return null
        /// </returns>
        private Salary GetLastSalary(int employeeNumber)
        {
            var salaries = db.Salaries.Where(x => x.employeeNumber == employeeNumber).OrderByDescending(x => x.fromDate);
            return (salaries.Count() > 0) ? salaries.First() : null;
        }

        /// <summary>
        /// Gets the last title.
        /// </summary>
        /// <param name="employeeNumber">The employee number.</param>
        /// <returns>
        /// Returns the latest title, if there is
        /// no title return null
        /// </returns>
        private Title GetLastTitle(int employeeNumber)
        {
            var titles = db.Titles.Where(x => x.employeeNumber == employeeNumber).OrderByDescending(x => x.fromDate);
            return (titles.Count() > 0) ? titles.First() : null;
        }

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }
    }
}